package user_service

import (
	"errors"
	"fmt"
	"github.com/sirupsen/logrus"
	"gorm.io/gorm"
	"strconv"
	"study/server/global"
	"study/server/model/request"
	resp "study/server/model/response"
	"study/server/model/system"
	"study/server/utils/captcha"
	"study/server/utils/email"
	"study/server/utils/my_jwt"
	"study/server/utils/pwd"
)

type UserService struct{}

func (u *UserService) PutInfo(nickName string, id uint, dst string) (resp.UpdateInfoResp, error) {
	// 检查用户是否存在
	var user system.UserModel
	result := global.DB.Where("id = ?", id).First(&user)
	if result.Error != nil {
		if errors.Is(result.Error, gorm.ErrRecordNotFound) {
			return resp.UpdateInfoResp{}, errors.New("用户不存在")
		}
		logrus.Error("查询用户失败", result.Error)
		return resp.UpdateInfoResp{}, errors.New("查询用户失败")
	}
	// 更新用户信息
	user.NickName = nickName
	user.Avatar = dst
	result = global.DB.Where("id = ?", id).Updates(&user)
	if result.RowsAffected == 0 {
		return resp.UpdateInfoResp{}, errors.New("更新用户信息失败")
	}
	putResp := resp.UpdateInfoResp{
		UserID:   id,
		NickName: nickName,
		Avatar:   dst,
	}
	return putResp, nil
}

func (u *UserService) UpdatePwd(req *request.ModifyPwdReq, uid uint) error {
	// 根据用户ID查询用户信息
	var user system.UserModel
	err := global.DB.Where("id =?", uid).First(&user).Error
	if err != nil {
		logrus.Error("查询用户失败", err)
		return errors.New("用户不存在")
	}
	if req.OldPassword == req.RePassword {
		logrus.Error("两次原密码不一致", err)
		return errors.New("两次原密码不一致")
	}
	// 校验旧密码 --> 需要更新旧密码时，旧密码不能为空，为空代表不更新密码
	if !pwd.LiftedHash(user.UserPassword, req.OldPassword) && req.NewPassword != "" {
		logrus.Error("旧密码错误", err)
		return errors.New("旧密码错误")
	}
	// 更新用户信息
	if req.NewPassword != "" {
		// 加密新密码
		hashPwd, err := pwd.GenerateHash(req.NewPassword)
		if err != nil {
			logrus.Error("密码加密失败", err)
			return errors.New("密码加密失败")
		}
		user.UserPassword = hashPwd
	}
	// 保存用户信息
	err = global.DB.Where("id =?", uid).Updates(&user).Error
	if err != nil {
		logrus.Error("更新失败", err)
		return errors.New("更新失败")
	}

	return nil
}

func (u *UserService) Register(req *request.RegisterReq) error {
	// 判断验证码
	if _, err := email.Verify(req.EmailID, req.Email, req.EmailCode, true); err != nil {
		logrus.Error("验证码错误", err)
		return errors.New("验证码错误")
	}
	// 校验密码
	if req.Password != req.RePassword {
		logrus.Error("两次密码不一致")
		return errors.New("两次密码不一致")
	}
	// 判断邮箱是否被注册
	var user system.UserModel
	err := global.DB.Where("email =?", req.Email).First(&user).Error
	if err == nil {
		logrus.Error("邮箱已被注册")
		return errors.New("邮箱已被注册")
	}

	// 创建用户
	hashPwd, err := pwd.GenerateHash(req.Password)
	if err != nil {
		logrus.Error("密码加密失败", err)
		return errors.New("密码加密失败")
	}
	user = system.UserModel{
		UserName:     req.Email,
		UserPassword: hashPwd,
		Email:        req.Email,
	}
	err = global.DB.Create(&user).Error
	if err != nil {
		logrus.Error("注册失败", err)
		return errors.New("注册失败")
	}
	return nil
}

func (u *UserService) Login(req *request.LoginReq) (resp.LoginResp, error) {
	// 校验验证码
	if global.Config.Captcha.Enable {
		// 校验验证码
		if req.CaptchaID == "" || req.CaptchaCode == "" {
			logrus.Error("验证码不能为空")
			return resp.LoginResp{}, errors.New("验证码不能为空")
		}
		// 校验验证码 -- 不管验证码是否正确,都不删除验证码
		if !captcha.Store.Verify(req.CaptchaID, req.CaptchaCode, false) {
			logrus.Error("验证码错误")
			return resp.LoginResp{}, errors.New("验证码错误")
		}
	}

	// 根据用户名查看存储的密码是否与输入的密码匹配
	var user system.UserModel
	err := global.DB.Where("user_name =?", req.Name).Preload("RoleList").First(&user).Error
	if err != nil {
		logrus.Error("用户名或密码错误", err)
		return resp.LoginResp{}, errors.New("用户名或密码错误")
	}
	// 对查询到的密码解密
	if !pwd.LiftedHash(user.UserPassword, strconv.Itoa(req.Password)) {
		logrus.Error("用户名或密码错误")
		return resp.LoginResp{}, errors.New("用户名或密码错误")
	}

	var roleList []uint
	for _, m := range user.RoleList {
		roleList = append(roleList, m.ID)
	}

	// 生成token
	token, _ := my_jwt.GenerateToken(my_jwt.CustomClaims{
		UserID:   user.ID,
		Username: user.UserName,
		RoleList: roleList,
	})
	respLogin := resp.LoginResp{
		Token: token,
		User: resp.CustomUser{
			NickName: user.NickName,
			Avatar:   user.Avatar,
			Email:    user.Email,
		},
	}

	return respLogin, nil
}

func (u *UserService) GetUserByIDInfo(userID uint) (resp.GetUserInfoResp, error) {
	// 获取用户信息
	var rep resp.GetUserInfoResp
	err := global.DB.Model(&system.UserModel{}).Select("id,nick_name,avatar,email").Where("id =?", userID).First(&rep).Error
	if err != nil {
		logrus.Error("查询用户失败", err)
		return rep, errors.New("查询用户失败")
	}

	return rep, nil
}

func (u *UserService) BindEmail(req *request.BindEmailReq, uid uint) error {
	// 判断用户是否有邮箱绑定
	var user system.UserModel
	result := global.DB.Select("user_name,email").Where("id =?", uid).First(&user)
	if result.Error != nil {
		logrus.Error("查询用户失败", result.Error)
		return errors.New("查询用户失败")
	}
	// 如果邮箱存在则更新邮箱
	if user.Email != "" {
		if req.NewEmail == user.Email {
			logrus.Error("新邮箱不能与旧邮箱相同")
			return errors.New("新邮箱不能与旧邮箱相同")
		}
		// 新邮箱验证码验证
		if _, err := email.Verify(req.NewEmailID, req.NewEmail, req.Code, true); err != nil {
			logrus.Error("验证码错误", err)
			return errors.New("验证码错误")
		}
		// 更新邮箱
		user.UserName = req.NewEmail
		user.Email = req.NewEmail
	} else {
		fmt.Println(req.NewEmailID, req.NewEmail, req.Code)
		// 新邮箱验证码验证
		if _, err := email.Verify(req.NewEmailID, req.NewEmail, req.Code, true); err != nil {
			logrus.Error("验证码错误", err)
			return errors.New("验证码错误")
		}
		// 绑定邮箱
		user.UserName = req.NewEmail
		user.Email = req.NewEmail
	}
	// 保存用户信息
	err := global.DB.Where("id =?", uid).Updates(&user).Error
	if err != nil {
		logrus.Error("更新失败", err)
		return errors.New("更新失败")
	}
	return nil
}
